package com.lakers.notice.springboot.netty.processor;

import cn.hutool.core.bean.BeanUtil;
import com.lakers.notice.springboot.model.NoticeLoginInfo;
import com.lakers.notice.springboot.netty.ChannelAttrKey;
import com.lakers.notice.springboot.netty.CmdType;
import com.lakers.notice.springboot.netty.SendInfo;
import com.lakers.notice.springboot.netty.UserChannelCtxMap;
import com.lakers.notice.springboot.spi.UserAuthentication;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;


/**
 * 功能描述: LoginProcessor
 *
 * @author liqin(zxl)
 * @date 2024/5/3
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LoginProcessor extends AbstractMessageProcessor<NoticeLoginInfo> {


    @Autowired(required = false)
    private List<UserAuthentication> authentications;


    @Override
    public void process(ChannelHandlerContext ctx, NoticeLoginInfo data) {
        final String userId = data.getUserId();
        final Integer terminal = data.getTerminal();
        log.info("user login is:{}", data.getUserId());
        if (!CollectionUtils.isEmpty(authentications)){
            for (UserAuthentication authentication : authentications) {
                if (!authentication.authentication(userId, terminal)){
                    throw new RuntimeException("user[ "+ userId + "] authentication fail");
                }
            }
        }
        ChannelHandlerContext context = UserChannelCtxMap.getChannelCtx(userId, terminal);
        if (context != null && !ctx.channel().id().equals(context.channel().id())) {
            SendInfo<String> sendInfo = new SendInfo<>();
            sendInfo.setCmd(CmdType.FORCE_LOGOUT.getCmd());
            sendInfo.setContent("您已在其他地方登陆，将被强制下线");
            context.channel().writeAndFlush(sendInfo);
            log.info("异地登录，强制下线,userId:{}", userId);
        }
        UserChannelCtxMap.addChannelCtx(userId, terminal, ctx);
        AttributeKey<String> userIdAttr = AttributeKey.valueOf(ChannelAttrKey.USER_ID);
        ctx.channel().attr(userIdAttr).set(userId);
        AttributeKey<Integer> terminalAttr = AttributeKey.valueOf(ChannelAttrKey.TERMINAL_TYPE);
        ctx.channel().attr(terminalAttr).set(terminal);
        SendInfo<Object> sendInfo = new SendInfo<>();
        sendInfo.setCmd(CmdType.LOGIN.getCmd());
        ctx.channel().writeAndFlush(sendInfo);
    }

    @Override
    public NoticeLoginInfo transForm(Object o) {
        HashMap map = (HashMap) o;
        return BeanUtil.fillBeanWithMap(map, new NoticeLoginInfo(), false);
    }
}
